package com.dankegongyu.lib.common.util;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;

import com.zhihu.matisse.Matisse;
import com.zhihu.matisse.MimeType;
import com.zhihu.matisse.filter.Filter;
import com.zhihu.matisse.internal.entity.CaptureStrategy;
import com.zhihu.matisse.internal.entity.IncapableCause;
import com.zhihu.matisse.internal.entity.Item;
import com.zhihu.matisse.internal.utils.PhotoMetadataUtils;
import com.zhihu.matisse.internal.utils.SingleMediaScanner;

import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.core.content.FileProvider;
import androidx.core.os.EnvironmentCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;

/**
 * 相机和图库工具类
 * <p>
 * https://github.com/zhihu/Matisse/blob/master/matisse/src/main/java/com/zhihu/matisse/internal/utils/MediaStoreCompat.java
 */
@SuppressWarnings("ResultOfMethodCallIgnored")
public class DKMediaUtil {

    private static Uri photoUri = null;
    private static String photoPath = null;
    private static Uri cropUri = null;
    private static String cropPath = null;

    private DKMediaUtil() {
        throw new AssertionError("cannot be instantiated");
    }

    public static void startCamera(@NonNull final FragmentActivity activity, @NonNull String authority, int requestCode) {
        startCamera(activity, activity, authority, requestCode);
    }

    public static void startCamera(@NonNull Fragment fragment, @NonNull String authority, int requestCode) {
        startCamera(fragment.getActivity(), fragment, authority, requestCode);
    }

    /**
     * 调用相机
     *
     * @param activity    Activity
     * @param object      只接受 Activity | android.support.v4.app.Fragment
     * @param requestCode requestCode
     */
    private static void startCamera(final FragmentActivity activity, final Object object, @NonNull final String authority, final int requestCode) {
        photoUri = null;
        photoPath = null;
        cropUri = null;
        cropPath = null;
        DKPermission.requestCameraPermission(activity, new DKPermission.Callback() {
            @SuppressLint("ObsoleteSdkInt")
            @Override
            public void onResult(boolean granted) {
                if (granted) {
                    try {
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        File photoFile = createImageFile();
                        if (photoFile != null) {
                            photoPath = photoFile.getAbsolutePath();
                            photoUri = FileProvider.getUriForFile(activity, authority, photoFile);
                            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                                List<ResolveInfo> resInfoList = activity.getPackageManager()
                                        .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                                for (ResolveInfo resolveInfo : resInfoList) {
                                    String packageName = resolveInfo.activityInfo.packageName;
                                    activity.grantUriPermission(packageName, photoUri,
                                            Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                }
                            }

                            if (object instanceof Activity) {
                                ((Activity) object).startActivityForResult(intent, requestCode);
                            } else if (object instanceof Fragment) {
                                ((Fragment) object).startActivityForResult(intent, requestCode);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    DKToast.show("请打开相机和存储权限！");
                }
            }
        });
    }

    @Nullable
    private static File createImageFile() {
        try {
            // /storage/sdcard0/Pictures
            String dirPath = DKPathUtil.getExternalPicturesPath();
            File dir = new File(dirPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            // /storage/sdcard0/Pictures/PHOTO_12894738742.jpg
            File file = new File(dir, "PHOTO_" + System.currentTimeMillis() + ".jpg");
            // Handle the situation that user's external storage is not ready
            if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(file))) {
                return null;
            }
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Uri getPhotoUri() {
        return photoUri;
    }

    public static String getPhotoPath() {
        return photoPath;
    }

    public static Uri cropImage(Activity activity, Uri inputUri, @NonNull String authority, int requestCode) {
        return cropImage(activity, inputUri, 300, 300, authority, requestCode);
    }

    public static Uri cropImage(Activity activity, Uri inputUri, int outputX, int outputY, @NonNull String authority, int requestCode) {
        return cropImage(activity, inputUri, 1, 1, outputX, outputY, authority, requestCode);
    }

    public static Uri cropImage(Activity activity, Uri inputUri, int aspectX, int aspectY, int outputX, int outputY, @NonNull String authority, int requestCode) {
        try {
            Intent intent = new Intent("com.android.camera.action.CROP");
            intent.setDataAndType(inputUri, "image/*");

            // /storage/sdcard0/Pictures
            String dirPath = DKPathUtil.getExternalPicturesPath();
            File dir = new File(dirPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            // /storage/sdcard0/Pictures/CROP_12894738742.jpg
            cropPath = dirPath + File.separator + "CROP_" + System.currentTimeMillis() + ".jpg";
            File file = new File(cropPath);
            if (!file.exists()) {
                file.createNewFile();
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                cropUri = FileProvider.getUriForFile(activity, authority, file);
                List<ResolveInfo> resolvedIntentActivities = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) {
                    String packageName = resolvedIntentInfo.activityInfo.packageName;
                    activity.grantUriPermission(packageName, inputUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    activity.grantUriPermission(packageName, cropUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                }
            } else {
                cropUri = Uri.fromFile(file);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.putExtra("crop", "true");
            intent.putExtra("aspectX", aspectX); // 裁剪框比例
            intent.putExtra("aspectY", aspectY);
            intent.putExtra("outputX", outputX); // 输出图片大小
            intent.putExtra("outputY", outputY);
            intent.putExtra("scale", true); // 去黑边
            intent.putExtra("scaleUpIfNeeded", true); // 去黑边
            intent.putExtra("return-data", false);
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            intent.putExtra("noFaceDetection", true);
            activity.startActivityForResult(intent, requestCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cropUri;
    }

    public static Uri getCropUri() {
        return cropUri;
    }

    public static String getCropPath() {
        return cropPath;
    }

    public static void refreshGallery(Context context, String path) {
        refreshGallery(context, path, null);
    }

    public static void refreshGallery(Context context, String path, @Nullable SingleMediaScanner.ScanListener listener) {
        if (context == null || TextUtils.isEmpty(path)) {
            return;
        }
        try {
            new SingleMediaScanner(context.getApplicationContext(), path, new SingleMediaScanner.ScanListener() {
                @Override
                public void onScanFinish() {
                    Log.i("SingleMediaScanner", "scan finish!");
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存到相册
     *
     * @param context 上下文
     * @param file    文件
     */
    @Deprecated
    public static void refreshGallery(Context context, File file) {
        if (context == null || file == null || !file.exists()) {
            return;
        }
        // 把图片插入到系统图库
        try {
            MediaStore.Images.Media.insertImage(context.getContentResolver(),
                    file.getAbsolutePath(), file.getName(), file.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 通知图库更新
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
    }

    public static void release() {
        photoUri = null;
        photoPath = null;
        cropUri = null;
        cropPath = null;
    }

    /**
     * 选择图片
     *
     * @param activity      Activity
     * @param authority     FileProvider
     * @param maxSelectable 最多能选择的图片数量
     * @param requestCode   请求码
     */
    public static void selectPics(final FragmentActivity activity, @NonNull final String authority, final int maxSelectable, final int requestCode) {
        selectPics(activity, authority, com.zhihu.matisse.R.style.Matisse_Zhihu, maxSelectable, requestCode);
    }

    /**
     * 选择图片
     *
     * @param activity      Activity
     * @param authority     FileProvider
     * @param themeId       theme resource id. Default value is com.zhihu.matisse.R.style.Matisse_Zhihu.
     * @param maxSelectable 最多能选择的图片数量
     * @param requestCode   请求码
     */
    public static void selectPics(final FragmentActivity activity, @NonNull final String authority, @StyleRes final int themeId, final int maxSelectable, final int requestCode) {
        DKPermission.requestCameraPermission(activity, new DKPermission.Callback() {
            @Override
            public void onResult(boolean granted) {
                if (granted) {
                    try {
                        Matisse.from(activity)
                                .choose(MimeType.ofImage())
                                .showSingleMediaType(true)
                                .theme(themeId)
                                .countable(false)
                                .capture(true)
                                .captureStrategy(new CaptureStrategy(true, authority))
                                .maxSelectable(maxSelectable)
                                .gridExpectedSize(ScreenUtil.dp2px(120f))
                                .thumbnailScale(0.85f)
                                .imageEngine(new DKGlideEngine())
                                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                                .autoHideToolbarOnSingleTap(true)
                                .addFilter(new MatisseGifSizeFilter(320, 320, 5 * 1024 * 1024))
                                .forResult(requestCode);
                    } catch (Throwable e) {
                        e.printStackTrace();
                    }
                } else {
                    DKToast.show("请打开相机和存储权限！");
                }
            }
        });
    }

    private static class MatisseGifSizeFilter extends Filter {

        private int mMinWidth;
        private int mMinHeight;
        private int mMaxSize;

        MatisseGifSizeFilter(int minWidth, int minHeight, int maxSizeInBytes) {
            mMinWidth = minWidth;
            mMinHeight = minHeight;
            mMaxSize = maxSizeInBytes;
        }

        @Override
        public Set<MimeType> constraintTypes() {
            return new HashSet<MimeType>() {{
                add(MimeType.GIF);
            }};
        }

        @Override
        public IncapableCause filter(Context context, Item item) {
            if (!needFiltering(context, item))
                return null;

            Point size = PhotoMetadataUtils.getBitmapBound(context.getContentResolver(), item.getContentUri());
            if (size.x < mMinWidth || size.y < mMinHeight || item.size > mMaxSize) {
                return new IncapableCause(IncapableCause.DIALOG,
                        "长宽不小于 " + mMinWidth + "px，且大小不超过 " + String.valueOf(PhotoMetadataUtils.getSizeInMB(mMaxSize)) + "M");
            }
            return null;
        }
    }
}
